# -*- coding: utf-8 -*-
# created on 2016/12/13

from sympy import cancel, fraction, S, Union
from collections import namedtuple
from mathsolver.functions.base.objects import BaseInter
from mathsolver.functions.base import BaseFunction, BaseIneq, new_latex, BaseSymbolValue
from mathsolver.functions.hanshu.base import is_fenshi, is_sqrt, is_duishuhanshu
from mathsolver.functions.hanshu.hengchengli import HengChengLiRenYiXing
from mathsolver.functions.budengshi.qiubudengshicanshuzhi import QiuBuDengShiCanShuZhi

# 不等式的解集
budengshi_jieji = namedtuple('budengshi_jieji', ['budengshi', 'jieji'])
# 不等式在区间恒成立
budengshi_hengchengli = namedtuple('budengshi_hengchengli', ['budengshi', 'interval'])


class GenShiHanShuDingYiYu(BaseFunction):
    """hs036.已知根式函数定义域得不等式"""

    def solver(self, *args):
        func, dingyiyu = args
        inner_sqrt = func.expression.args[0]
        res = [inner_sqrt, '>=', 0]

        self.steps.append(["", "由题意知，%s ≥ 0 的解集为 %s" % (new_latex(inner_sqrt), new_latex(dingyiyu))])
        self.output.append(budengshi_jieji(BaseIneq(res), dingyiyu))
        self.label.add("已知根式函数定义域得不等式")
        return self


class DuiShuHanShuDingYiYu(BaseFunction):
    """hs037.已知对数函数定义域得不等式"""

    def solver(self, *args):
        func, dingyiyu = args
        f, symbol = func.expression, func.var
        inner_duishu = f.as_independent(symbol)[1].args[0]
        res = [inner_duishu, '>', 0]

        self.steps.append(["", "由题意知，%s > 0 的解集为 %s" % (new_latex(inner_duishu), new_latex(dingyiyu))])
        self.output.append(budengshi_jieji(BaseIneq(res), dingyiyu))
        self.label.add("已知对数函数定义域得不等式")
        return self


class GenShiHanShuDingYiYuR(BaseFunction):
    """hs038.根式函数定义域为R得不等式"""

    def solver(self, *args):
        func = args[0]
        inner_sqrt = func.expression.args[0]
        res = [inner_sqrt, '>', 0]

        self.steps.append(["", "由题意知，%s > 0 在 x ∈ R 上恒成立" % new_latex(inner_sqrt)])
        self.output.append(budengshi_hengchengli(BaseIneq(res), S.Reals))
        self.label.add("根式函数定义域为R得不等式")
        return self


class FenShiHanShuDingYiYuR(BaseFunction):
    """hs039.分式函数定义域为R得不等式"""

    def solver(self, *args):
        func = args[0]
        f = cancel(func.expression)
        fenzhi, fenmu = fraction(f)
        res = [fenmu, '!=', 0]

        self.steps.append(["", "由题意知，%s ≠ 0 在 x ∈ R 上恒成立" % new_latex(fenmu)])
        self.output.append(budengshi_hengchengli(BaseIneq(res), S.Reals))
        self.label.add("分式函数定义域为R得不等式")
        return self


class DuiShuHanShuDingYiYuR(BaseFunction):
    """hs040.对数函数定义域为R得不等式"""

    def solver(self, *args):
        func = args[0]
        f, symbol = func.expression, func.var
        inner_duishu = f.as_independent(symbol)[1].args[0]
        res = [inner_duishu, '>', 0]

        self.steps.append(["", "由题意知，%s > 0 在 x ∈ R 上恒成立" % new_latex(inner_duishu)])
        self.output.append(budengshi_hengchengli(BaseIneq(res), S.Reals))
        self.label.add("对数函数定义域为R得不等式")
        return self


class GenShiHanShuQuJianYouYiYi(BaseFunction):
    """hs041.根式函数在区间上有意义得不等式"""

    def solver(self, *args):
        func, belong = args
        inner_sqrt = func.expression.args[0]
        res = [inner_sqrt, '>', 0]

        self.steps.append(["", "由题意知，%s > 0 在 %s 上恒成立" % (new_latex(inner_sqrt), belong.printing())])
        self.output.append(budengshi_hengchengli(BaseIneq(res), belong))
        self.label.add("已知根式函数定义域得不等式")
        return self


class DuiShuHanShuQuJianYouYiYi(BaseFunction):
    """hs042.对数函数在区间上有意义得不等式"""

    def solver(self, *args):
        func, belong = args
        f, symbol = func.expression, func.var
        inner_duishu = f.as_independent(symbol)[1].args[0]
        res = [inner_duishu, '>', 0]

        self.steps.append(["", "由题意知，%s > 0 在 %s 上恒成立" % (new_latex(inner_duishu), belong.printing())])
        self.output.append(budengshi_hengchengli(BaseIneq(res), belong))
        self.label.add("已知对数函数定义域得不等式")
        return self


class HanShuDingYiYuRQiuCan(BaseFunction):
    """函数定义域为R求参数"""

    def solver(self, *args):
        func = args[0]
        if len(args) == 2:
            assert isinstance(args[1], BaseInter)
            inter = args[1].interval
            left, right, lopen, ropen = inter.args
            assert left.is_infinite and right.is_infinite
        f, symbol = func.expression, func.var

        # 判断函数类型，得到恒成立条件
        if is_sqrt(f):
            step_hengchengli = GenShiHanShuDingYiYuR().solver(func)
        elif is_fenshi(f):
            step_hengchengli = FenShiHanShuDingYiYuR().solver(func)
        elif is_duishuhanshu(f, symbol):
            step_hengchengli = DuiShuHanShuDingYiYuR().solver(func)
        else:
            raise NotImplementedError("unknown function %s" % func.printing())
        self.steps.extend(step_hengchengli.steps)

        # 不等式恒成立问题
        ineq, qujian = step_hengchengli.output[0]
        left, op, right = ineq.value

        # 对 ≠ 特殊处理
        if op == '!=':
            ineq1 = [left, '>', right]
            ineq2 = [left, '<', right]
            self.steps.append(["", "由题意知 {l} > {r} 或 {l} < {r} 恒成立".format(l=left, r=right)])
            step_hengchengli1 = HengChengLiRenYiXing().solver(BaseIneq(ineq1))
            step_hengchengli2 = HengChengLiRenYiXing().solver(BaseIneq(ineq2))
            self.steps.extend(step_hengchengli1.steps)
            self.steps.extend(step_hengchengli2.steps)
            k1, v1 = [[k, v] for k, v in step_hengchengli1.output[0].value.items()][0]
            k2, v2 = [[k, v] for k, v in step_hengchengli2.output[0].value.items()][0]
            res = BaseSymbolValue({k1: Union(v1, v2)})
            self.steps.append(["", "综上，%s" % res.printing()])
            self.output.append(res)
        else:
            step_hengchengli = HengChengLiRenYiXing().solver(ineq)
            self.steps.extend(step_hengchengli.steps)
            self.output = step_hengchengli.output
            self.label.add("函数定义域为R求参数")
        return self


class HanShuQuJianYouYiYiQiuCan(BaseFunction):
    """函数在区间上有意义求参数"""

    def solver(self, *args):
        func, qujian = args
        f, symbol = func.expression, func.var

        # 判断函数类型，得到恒成立条件
        if is_sqrt(f):
            step_hengchengli = GenShiHanShuQuJianYouYiYi().solver(func, qujian)
        elif is_duishuhanshu(f, symbol):
            step_hengchengli = DuiShuHanShuQuJianYouYiYi().solver(func, qujian)
        else:
            raise NotImplementedError("unknown function %s" % func.printing())
        self.steps.extend(step_hengchengli.steps)

        # 不等式恒成立问题
        ineq, qujian = step_hengchengli.output[0]
        step_hengchengli = HengChengLiRenYiXing().solver(ineq, qujian)
        self.steps.extend(step_hengchengli.steps)
        self.output = step_hengchengli.output
        self.label.add("函数在区间上有意义求参数")
        return self


class HanShuDingYiYuQiuCan(BaseFunction):
    """已知函数定义域求参数"""

    def solver(self, *args):
        func, dingyiyu = args
        f, symbol = func.expression, func.var

        # 判断函数类型，得到恒成立条件
        if is_sqrt(f):
            step_jieji = GenShiHanShuDingYiYu().solver(func, dingyiyu)
        elif is_duishuhanshu(f, symbol):
            step_jieji = DuiShuHanShuDingYiYu().solver(func, dingyiyu)
        else:
            raise NotImplementedError("unknown function %s" % func.printing())
        self.steps.extend(step_jieji.steps)

        # 已知不等式解集求参数
        ineq, dingyiyu = step_jieji.output[0]
        step_qiucan = QiuBuDengShiCanShuZhi().solver(ineq, dingyiyu)
        self.steps.extend(step_qiucan.steps)
        self.output = step_qiucan.output
        self.label.add("已知函数定义域求参数")

        return self


if __name__ == '__main__':
    pass
